2.2: Siklus Hidup Aktivitas dan Status Instance
Daftar Isi:
- Yang harus sudah Anda KETAHUI
- Yang akan Anda PELAJARI
- Yang akan Anda LAKUKAN
- Ringkasan Aplikasi
- Tugas 1. Menambahkan callback siklus hidup ke TwoActivities
- Tugas 2. Menyimpan dan memulihkan aktivitas status
- Tantangan penyusunan kode
- Rangkuman
- Konsep terkait
Dalam praktik ini Anda akan belajar lebih banyak tentang siklus hidup aktivitas. Siklus hidup aktivitas adalah serangkaian status tempat aktivitas mungkin berada sepanjang daur hidupnya, mulai dari saat aktivitas pertama dibuat hingga dihancurkan dan sistem mengklaim kembali sumber daya aktivitas tersebut. Saat pengguna menelusuri di antara aktivitas dalam aplikasi (di dalam dan di luar aplikasi juga), masing-masing aktivitas tersebut bertransisi di antara status yang berbeda dalam siklus hidup aktivitas.
Setiap tahap dalam siklus hidup aktivitas memiliki metode callback yang cocok (onCreate(), onStart(), onPause(), dan lainnya). Saat sebuah aktivitas mengubah status, metode callback terkait akan dipanggil. Anda sudah melihat sala dari metode ini: onCreate(). Dengan mengganti metode callback siklus hidup dalam kelas aktivitas, Anda bisa mengubah perilaku default bagaimana aktivitas berperilaku untuk merespons pengguna atau tindakan sistem yang berbeda.
Perubahan pada status aktivitas juga dapat terjadi sebagai respons terhadap perubahan konfigurasi perangkat seperti memutar perangkat dari orientasi potret ke lanskap. Perubahan konfigurasi ini menyebabkan aktivitas dihancurkan dan sepenuhnya dibuat ulang dalam status default-nya, yang dapat menyebabkan hilangnya informasi yang telah dimasukkan pengguna ke dalam aktivitas tersebut. Penting untuk mengembangkan aplikasi untuk menghindarinya, agar pengguna tidak bingung. Nanti dalam praktik ini kita akan bereksperimen dengan perubahan konfigurasi dan belajar cara mempertahankan status aktivitas sebagai respons terhadap perubahan konfigurasi atau peristiwa siklus hidup Aktivitas lainnya.
Dalam praktik ini Anda akan menambahkan pernyataan pencatatan log ke aplikasi TwoActivities dan mengamati perubahan siklus hidup saat menggunakan aplikasi dengan berbagai cara. Lalu Anda akan mulai bekerja dengan perubahan tersebut dan mencari tahu cara menangani input pengguna dalam kondisi ini..
Yang harus sudah Anda KETAHUI
Dari praktik sebelumnya, Anda harus sudah bisa:
- Membuat dan menjalankan proyek aplikasi dalam Android Studio.
- Menambahkan pernyataan log ke aplikasi dan menampilkan log tersebut dalam Android Monitor (logcat).
- Memahami dan bekerja dengan aktivitas dan intent, dan nyaman berinteraksi dengan keduanya.
Yang akan Anda PELAJARI
Anda akan belajar:
- Memahami siklus hidup aktivitas dan kapan aktivitas dibuat, dijeda, dihentikan, dan dimusnahkan.
- Memahami metode callback siklus hidup yang terkait dengan perubahan aktivitas.
- Memahami efek tindakan seperti perubahan konfigurasi yang dapat menghasilkan peristiwa siklus hidup aktivitas.
- Mempertahankan status aktivitas di seluruh peristiwa siklus hidup.
Yang akan Anda LAKUKAN
Dalam praktik ini Anda akan:
- Memperluas aplikasi TwoActivities dari praktik sebelumnya untuk mengimplementasikan berbagai callback siklus hidup aktivitas untuk menyertakan pernyataan pencatatan log.
- Mengamati perubahan status saat aplikasi berjalan dan Anda berinteraksi dengan aktivitas di dalam aplikasi.
- Memodifikasi aplikasi untuk mempertahankan status instance aktivitas yang tanpa terduga dibuat ulang sebagai respons terhadap perilaku pengguna atau perubahan konfigurasi pada perangkat.
Ringkasan Aplikasi
Untuk praktik ini Anda akan menambahkan ke aplikasi TwoActivities. Aplikasi ini terlihat dan berperilaku kurang lebih sama dengan yang ada pada bab terakhir: dengan dua aktivitas dan dua pesan yang bisa Anda kirimkan di antara keduanya. Perubahan yang Anda buat pada aplikasi dalam praktik ini tidak akan memengaruhi perilaku pengguna yang terlihat.
Tugas 1. Menambahkan Callback Siklus Hidup ke TwoActivities
Dalam tugas ini Anda akan mengimplementasikan semua metode callback siklus hidup aktivitas untuk mencetak pesan ke logcat saat metode itu dipanggil. Pesan log ini akan mengizinkan Anda melihat kapan status perubahan siklus hidup aktivitas dan bagaimana perubahan status siklus hidup memengaruhi aplikasi Anda saat aplikasi berjalan.
1.1 (Opsional) Menyalin Proyek TwoActivities
Untuk tugas dalam praktik ini, Anda akan memodifikasi proyek [TwoActivities] yang sudah ada(https://github.com/google-developer-training/android-fundamentals/tree/master/TwoActivities) yang dibuat pada praktik sebelumnya. Jika memilih untuk menjaga proyek TwoActivities sebelumnya tetap utuh, ikuti langkah-langkah pada Appendix untuk membuat salinan proyek.
1.2 Mengimplementasikan callback ke MainActivity
- Buka java/com.example.android.twoactivities/MainActivity.
- Dalam metode onCreate(), tambahkan pernyataan log berikut:
Log.d(LOG_TAG, "-------"); Log.d(LOG_TAG, "onCreate");
Tambahkan metode baru untuk callback onStart(), dengan pernyataan ke log untuk peristiwa tersebut:
@Override public void onStart(){ super.onStart(); Log.d(LOG_TAG, "onStart"); }
TIPS: Pilih Code > Override Methods dalam Android Studio. Dialog muncul dengan semua metode yang mungkin dan bisa Anda gantikan dalam kelas. Memilih satu atau beberapa metode callback dari daftar menyisipkan template lengkap untuk metode tersebut, termasuk panggilan wajib ke superkelas.
Gunakan metode onStart() sebagai template untuk mengimplementasikan callback siklus hidup lainnya:
- onPause()
- onRestart()
- onResume()
- onStop()
- onDestroy()
Semua metode callback memiliki tanda tangan yang sama (kecuali untuk nama). Jika Anda menyalin dan menempel onStart() untuk membuat metode callback lain, jangan lupa untuk memperbarui kontennya agar memanggil metode yang sama dalam superkelas dan mencatat log metode yang benar.
Bangun dan jalankan aplikasi Anda.
Kode Solusi (bukan seluruh kelas):
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
mMessageEditText = (EditText) findViewById(R.id.editText_main);
mReplyHeadTextView = (TextView) findViewById(R.id.text_header_reply);
mReplyTextView = (TextView) findViewById(R.id.text_message_reply);
}
@Override
public void onStart(){
super.onStart();
Log.d(LOG_TAG, "onStart");
}
@Override
public void onRestart() {
super.onRestart();
Log.d(LOG_TAG, "onRestart");
}
@Override
public void onResume() {
super.onResume();
Log.d(LOG_TAG, "onResume");
}
@Override
public void onPause() {
super.onPause();
Log.d(LOG_TAG, "onPause");
}
@Override
public void onStop() {
super.onStop();
Log.d(LOG_TAG, "onStop");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(LOG_TAG, "onDestroy");
}
1.3 Mengimplementasikan callback siklus hidup dalam SecondActivity
Karena sekarang Anda sudah mengimplementasikan metode callback siklus hidup untuk MainActivity, lakukan hal yang sama untuk SecondActivity.
- Buka java/com.example.android.twoactivities/SecondActivity.
- Di bagian atas kelas, tambahkan konstanta untuk variabel LOG_TAG:
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
- Tambahkan callback siklus hidup dan pernyataan log ke aktivitas kedua. (Anda juga bisa menyalin dan menempel metode callback dari MainActivity)
- Tambahkan pernyataan log ke metode returnReply(), tepat sebelum metode finish():
Log.d(LOG_TAG, "End SecondActivity");
Kode Solusi (bukan seluruh kelas):
private static final String LOG_TAG = SecondActivity.class.getSimpleName();
public void returnReply(View view) {
String reply = mReply.getText().toString();
Intent replyIntent = new Intent();
replyIntent.putExtra(EXTRA_REPLY, reply);
setResult(RESULT_OK, replyIntent);
Log.d(LOG_TAG, "End SecondActivity");
finish();
}
@Override
protected void onStart() {
super.onStart();
Log.d(LOG_TAG, "onStart");
}
@Override
public void onRestart() {
super.onRestart();
Log.d(LOG_TAG, "onRestart");
}
@Override
public void onResume() {
super.onResume();
Log.d(LOG_TAG, "onResume");
}
@Override
public void onPause() {
super.onPause();
Log.d(LOG_TAG, "onPause");
}
@Override
public void onStop() {
super.onStop();
Log.d(LOG_TAG, "onStop");
}
@Override
public void onDestroy() {
super.onDestroy();
Log.d(LOG_TAG, "onDestroy");
}
1.4 Amati log saat aplikasi berjalan
- Jalankan aplikasi Anda.
- Klik Android Monitor di bawah Android Studio untuk membuka Android Monitor.
- Pilih tab logcat.
Ketik "Activity" dalam kotak pencarian Android Monitor.
Logcat Android bisa menjadi sangat panjang dan berantakan. Karena variabel LOG_TAG di setiap kelas berisi kata MainActivity atau SecondActivity, kata kunci ini memungkinkan Anda memfilter log hanya untuk hal-hal yang Anda minati.
- Bereksperimenlah dengan aplikasi dan catat bahwa peristiwa siklus hidup terjadi untuk merespons tindakan yang berbeda. Khususnya, coba hal-hal berikut ini:
- Gunakan aplikasi dengan normal (mengirim pesan, membalas dengan pesan lain.)
- Gunakan tombol kembali untuk kembali dari aktivitas kedua ke aktivitas utama.
- Gunakan panah kiri pada bilah tindakan untuk kembali dari aktivitas kedua ke aktivitas utama.
- Putar perangkat pada aktivitas utama dan kedua pada waktu yang berlainan dalam aplikasi dan amati apa yang terjadi dalam log dan layar.TIPS:Jika menjalankan aplikasi dalam emulator, Anda bisa menyimulasikan putaran dengan Ctrl-F11 atau Ctrl-Fn-F11.
- Tekan tombol ringkasan (tombol kotak di sebelah kanan Beranda) dan tutup aplikasi (ketuk X).
- Kembali ke layar beranda dan mulai ulang aplikasi Anda.
Tantangan penyusunan kode
Tantangan: Amati onDestroy() pada khususnya. Mengapa onDestroy() kadang dipanggil (setelah mengeklik tombol kembali, atau saat perangkat diputar) dan bukan yang lainnya (menghentikan dan memulai ulang aplikasi secara manual)?
[Tugas 2. Menyimpan dan memulihkan status instance aktivitas.
Tergantung pada sumber daya sistem dan perilaku pengguna, aktivitas dalam aplikasi Anda dapat dimusnahkan dan dibuat ulang jauh lebih sering dari yang Anda pikirkan. Anda mungkin telah memperhatikan serangkaian aktivitas ini pada bagian sebelumnya saat memutar perangkat atau emulator. Memutar perangkat adalah salah satu contoh perubahan konfigurasi. Walaupun putaran adalah yang paling umum, semua hasil perubahan konfigurasi mengakibatkan aktivitas saat ini dimusnahkan dan dibuat ulang seperti baru. Jika Anda tidak mempertimbangkan perilaku ini dalam kode, saat perubahan konfigurasi terjadi layout aktivitas mungkin akan kembali ke tampilan default dan nilai awalnya, dan pengguna Anda bisa kehilangan tempat, data, atau status perkembangannya dalam aplikasi Anda.
Status setiap aktivitas disimpan sebagai serangkaian pasangan kunci/nilai dalam objek Bundel bernama status instance aktivitas. Sistem menyimpan informasi status default ke bundel status instance sebelum aktivitasnya dihentikan, dan meneruskan bundel itu ke instance aktivitas baru untuk disimpan.
Agar aktivitas tidak kehilangan data saat secara tidak terduga dimusnahkan dan dibuat ulang, Anda perlu mengimplementasikan metode onSaveInstanceState(). Sistem akan memanggil metode ini pada aktivitas Anda (di antara onPause() dan onStop()) saat ada kemungkinan aktivitas akan dimusnahkan dan dibuat ulang.
Data yang disimpan pada status instance spesifik untuk instance aktivitas spesifik ini saja selama sesi aplikasi saat ini. Saat Anda berhenti dan memulai ulang sesi aplikasi baru, status instance aktivitas hilang dan aktivitas Anda akan kembali ke tampilan default-nya. Jika Anda perlu menyimpan data pengguna antar sesi aplikasi, gunakan database atau preferensi bersama. Anda akan mempelajari tentang keduanya pada praktik berikutnya.
2.1 Simpan status instance aktivitas dengan onSaveInstanceState()
Anda mungkin telah memperhatikan bahwa memutar perangkat tidak memengaruhi status aktivitas kedua sama sekali. Ini karena layout dan status aktivitas kedua dihasilkan dari layout dan intent yang mengaktifkannya. Bahkan jika aktivitas tersebut dibuat ulang, intent-nya akan tetap ada di sana dan data di dalam intent tersebut masih digunakan setiap onCreate() aktivitas kedua dipanggil.
Selain itu, Anda mungkin memperhatikan bahwa dalam kedua aktivitas setiap teks yang Anda ketik ke dalam pesan atau balasan EditTexts dipertahankan bahkan ketika perangkat diputar. Ini karena informasi status beberapa tampilan dalam layout secara otomatis disimpan di semua perubahan konfigurasi, dan nilai saat ini EditText adalah salah satu kasus ini.
Satu-satunya status aktivitas yang harus diperhatikan adalah TextView untuk header balasan dan teks balasan dalam aktivitas utama. Kedua TextView secara default tidak terlihat, hanya muncul ketika Anda mengirimkan pesan kembali ke aktivitas utama dari aktivitas kedua.
Dalam tugas ini Anda akan menambahkan kode untuk mempertahankan status instance kedua TextView menggunakan onSaveInstanceState().
- Buka java/com.example.android.twoactivities/MainActivity.
- Tambahkan implementasi skeleton onSaveInstanceState() ke aktivitas, atau gunakan Code > Override Methods untuk menyisipkan pengganti kerangka.
@Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); }
Periksa untuk melihat apakah header saat ini terlihat, dan jika demikian letakkan status visibilitas ke dalam bundel status dengan metode putBoolean() dan kunci "reply_visible".
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) { outState.putBoolean("reply_visible", true); }
Ingat bahwa header dan teks balasan ditandai sebagai tidak terlihat sampai ada balasan dari aktivitas kedua. Jika header terlihat, maka ada data balasan yang perlu disimpan. Kita hanya berfokus pada status visibilitas -- teks header sebenarnya tidak perlu disimpan, karena teks tersebut tidak pernah berubah.
Dalam pemeriksaan yang sama, tambahkan teks balasan ke dalam bundel.
outState.putString("reply_text", mReplyTextView.getText().toString());
Jika header terlihat Anda bisa mengasumsikan bahwa pesan balasan juga terlihat. Anda tidak perlu menguji atau menyimpan status visibilitas pesan balasan saat ini. Hanya teks sebenarnya pesan yang masuk ke dalam bundel status dengan kunci "reply_text".
Kita hanya menyimpan tampilan yang dapat berubah setelah aktivitas dibuat.
Tampilan lain dalam aplikasi (EditText, Tombol) dapat dibuat ulang dari layout default kapan saja.
Catatan: Sistem akan menyimpan status beberapa tampilan, seperti konten EditText.
Kode Solusi (bukan seluruh kelas):
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// If the heading is visible, we have a message that needs to be saved.
// Otherwise we're still using default layout.
if (mReplyHeadTextView.getVisibility() == View.VISIBLE) {
outState.putBoolean("reply_visible", true);
outState.putString("reply_text", mReplyTextView.getText().toString());
}
}
2.2. Memulihkan status instance aktivitas dalam onCreate()
Setelah menyimpan status instance aktivitas, Anda juga perlu memulihkannya saat aktivitas dibuat ulang. Anda bisa melakukannya dalam onCreate(), atau dengan mengimplementasikan callback onRestoreInstanceState(), yang dipanggil setelah onStart() setelah aktivitas dibuat.
Biasanya tempat terbaik untuk memulihkan status aktivitas adalah di onCreate(), untuk memastikan antarmuka pengguna termasuk statusnya tersedia secepat mungkin. Kadang lebih nyaman melakukannya dalam onRestoreInstanceState() setelah semua inisialisasi dilakukan, atau untuk mengizinkan subkelas memutuskan apakah akan menggunakan implementasi default Anda.
Dalam metode onCreate(), tambahkan tes untuk memastikan bundelnya tidak null.
if (savedInstanceState != null) { }
Saat aktivitas dibuat, sistem meneruskan bundel status ke onCreate() karena itu hanya argumen. Pertama kali onCreate() dipanggil dan aplikasi Anda dimulai, bundelnya null, tidak ada status saat pertama kali aplikasi dimulai. Panggilan berikutnya ke onCreate() memiliki bundel yang diisi dengan data apa pun yang Anda simpan dalam onSaveInstanceState().
- Dalam pemeriksaan tersebut, dapatkan visibilitas saat ini (benar atau salah) dari bundel dengan kunci "reply_visible"
if (savedInstanceState != null) { boolean isVisible = savedInstanceState.getBoolean("reply_visible"); }
Tambahkan tes di bawah baris sebelumnya untuk variabel isVisible.
if (isVisible) { }
Jika ada kunci reply_visible" dalam bundel status (maka isVisible benar), kita perlu memulihkan statusnya.
- Dalam tes isVisible, buat header-nya terlihat.
mReplyHeadTextView.setVisibility(View.VISIBLE);
- Dapatkan pesan balasan teks dari bundel dengan kunci "reply_text", dan setel TextView balasan untuk menunjukkan string tersebut.
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
- Jadikan TextView balasan terlihat juga:
mReplyTextView.setVisibility(View.VISIBLE);
- Jalankan aplikasi. Coba putar perangkat atau emulator untuk memastikan bahwa pesan balasan (jika ada) tetap ada di layar setelah aktivitas dibuat ulang.
Kode Solusi (bukan seluruh kelas):
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.d(LOG_TAG, "-------");
Log.d(LOG_TAG, "onCreate");
// Initialize all the view variables.
mMessageEditText = (EditText) findViewById(R.id.editText_main);
mReplyHeadTextView = (TextView) findViewById(R.id.text_header_reply);
mReplyTextView = (TextView) findViewById(R.id.text_message_reply);
// Restore the saved state. See onSaveInstanceState() for what gets saved.
if (savedInstanceState != null) {
boolean isVisible = savedInstanceState.getBoolean("reply_visible");
// Show both the header and the message views. If isVisible is
// false or missing from the bundle, use the default layout.
if (isVisible) {
mReplyHeadTextView.setVisibility(View.VISIBLE);
mReplyTextView.setText(savedInstanceState.getString("reply_text"));
mReplyTextView.setVisibility(View.VISIBLE);
}
}
}
Kode Solusi
Proyek Android Studio: Siklus Hidup TwoActivities
Tantangan penyusunan kode
Tantangan: Membuat aplikasi pembuat daftar belanja dengan dua aktivitas. Aktivitas utama berisi daftar itu sendiri, yang dibuat dari sepuluh tampilan teks (kosong). Tombol pada aktivitas utama dilabeli "Add Item" membuka aktivitas kedua yang berisi daftar barang belanjaan (Keju, Nasi, Apel, dan seterusnya). Gunakan Tombol untuk menampilkan item. Memilih item akan mengembalikan Anda ke aktivitas utama, dan memperbarui TextView kosong untuk menyertakan barang yang dipilih.
Gunakan intent untuk meneruskan informasi di antara dua aktivitas. Pastikan status daftar belanja saat ini disimpan saat Anda memutar perangkat.
Rangkuman
- Siklus hidup aktivitas adalah serangkaian status tempat aktivitas bermigrasi, yang dimulai saat aktivitas baru dibuat dan berakhir saat sistem Android mengklaim kembali sumber daya aktivitas tersebut.
- Saat pengguna bernavigasi di antara aktivitas, di dalam dan di luar aplikasi, setiap aktivitas bergerak di antara status dalam siklus hidup aktivitas.
- Setiap status dalam siklus hidup aktivitas memiliki metode callback yang sesuai dan dapat Anda ganti dalam kelas aktivitas. Metode siklus hidup tersebut adalah:
- onCreate()
- onStart()
- onPause()
- onRestart()
- onResume()
- onStop()
- onDestroy()
- Mengganti metode callback siklus hidup mengizinkan Anda menambahkan perilaku yang terjadi saat aktivitas bertransisi ke status tersebut.
- Anda dapat menambahkan metode pengganti kerangka ke kelas dalam Android Studio dengan Code > Override.
- Perubahan konfigurasi perangkat seperti hasil putaran dalam aktivitas dimusnahkan dan dibuat ulang seperti baru.
- Porsi status aktivitas tersebut dipertahankan pada perubahan konfigurasi, termasuk nilai saat ini EditTexts. Untuk semua data lainnya, Anda harus secara eksplisit menyimpan data sendiri.
- Simpan status instance aktivitas dalam metode onSaveInstanceState().
- Data status instance disimpan sebagai pasangan kunci/nilai dalam Bundel. Gunakan metode Bundel untuk meletakkan data ke dalam dan mengeluarkan data dari bundel.
- Pulihkan status instance dalam onCreate(), cara yang sebaiknya dipilih, atau onRestoreInstanceState().
Konsep terkait
Dokumentasi konsep terkait ada di Dasar-Dasar Developer Android: Konsep.
Ketahui selengkapnya
- Aktivitas (Panduan API)
- Aktivitas (Referensi API)
- Mengelola Siklus Hidup Aktivitas
- Membuat Ulang Aktivitas
- Menangani Perubahan Waktu Proses